package ias.deepsearch.com.helper.model.view_data;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.webkit.WebView;
import android.widget.AbsListView;
import android.widget.GridView;
import android.widget.TextView;

import com.alibaba.fastjson.annotation.JSONField;

import java.io.Serializable;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import ias.deepsearch.com.helper.util.normal.ViewUtil;

/**
 * Created by vector on 16/5/11.
 */
public class ViewTree implements Serializable{



    String package_name;

    public ViewNode root;

    Context context;

    int relativeCount;

    @JSONField(serialize=false)
    public static Class<? extends View>[] filtsBys = new Class[]{AbsListView.class, GridView.class};


    @JSONField(serialize=false)
    int screen_width;


    public ViewNode getRoot() {
        return root;
    }

    public void setRoot(ViewNode root) {
        this.root = root;
    }

    public ViewTree() {
    }

    public ViewTree(Context context, View decorView, String package_name){


        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        screen_width = wm.getDefaultDisplay().getWidth();

        relativeCount = 0;
        this.package_name = package_name;
        this.context = context;
        if(decorView !=null) {
            root = construct(decorView, 0);
        }
        int beginID = 0;

        ArrayDeque<ViewNode> queue=new ArrayDeque<>();
        ArrayDeque<ViewNode> queue1=new ArrayDeque<>();
        queue.add(root);
        while(!queue.isEmpty()){
            ViewNode node1 = queue.remove();
            node1.setId("id" + beginID);
            //node1.setText(ViewUtil.getLast(node1.getViewTag()));
            node1.setText(node1.getViewTag() + " [" + node1.getX() + " ," + node1.getY()+ "][" + (node1.getX()+node1.getWidth()) + " ," + (node1.getY() + node1.getHeight())+ "]");
            beginID++;
            queue.addAll(node1.getChildren());
        }

        queue1.add(root);
        while(!queue1.isEmpty()){
            ViewNode node1 = queue1.remove();
            node1.setViewNodeIDRelative(relativeCount++);
            if(!node1.isList){
                queue1.addAll(node1.getChildren());
            }
        }
    }




    ViewNode construct(View rootView, int depth){

        if(rootView != null) {

            if (rootView.getVisibility() == View.GONE)
                return null;
            int[] position = new int[2];
            rootView.getLocationOnScreen(position);

            if ((position[0] + rootView.getWidth()) < 0 || (position[0]) > screen_width)
                return null;


            //设置View点击的位置（中间）

            ViewNode now = new ViewNode();
            now.setView(rootView);
            now.setDepth(depth);

            now.setX(position[0]);
            now.setY(position[1]);
            now.setWidth(rootView.getWidth());
            now.setHeight(rootView.getHeight());
            now.setChildren(new LinkedList<ViewNode>());
            now.setViewTag(rootView.getClass().getName());
            now.isList = false;

            if(rootView.getId()!=-1) {
                now.setResource_id(ViewUtil.getFieldName(context, package_name, rootView.getId()));
            }

            if (rootView instanceof TextView) {
                now.setViewText(((TextView) rootView).getText().toString());
            }
            else
                now.setViewText("");


            now.setTotal_view(1);

            if (rootView instanceof WebView){
                now.setViewText("It is a WebView");
            }

            if (rootView instanceof ViewGroup) {

                int child_Num = ((ViewGroup)rootView).getChildCount();
                List<ViewNode> child_list = new ArrayList<>();
                String hash_string = now.calString();
                String relate_hash_string = now.calStringWithoutPosition();


                for(int i = 0; i < child_Num; i++){
                    View child = ((ViewGroup)rootView).getChildAt(i);
                    ViewNode child_node = construct(child, depth + 1);
                    if (child_node == null)
                        continue;
                    child_node.setParent(now);
                    child_list.add(child_node);
                    now.setTotal_view(now.getTotal_view() + child_node.getTotal_view());
                }
                Collections.sort(child_list);
                child_Num = child_list.size();
                boolean isList = isList(rootView);

                if(!isList){
                    if(child_Num <= 1){
                        isList = false;
                    }else{
                        ArrayList<Integer> cnt = new ArrayList<>();
                        cnt.add(child_list.get(0).getNodeRelateHash());
                        int ccnt = 0;
                        for (int i = 1; i < child_Num; i++) {
                            int id = child_list.get(i).getNodeRelateHash();
                            if (cnt.contains(id)) {
                                ++ccnt;
                            }
                            else
                                cnt.add(id);
                        }
                        if (ccnt >= child_list.size() * 2 / 3)
                            isList = true;
                    }
                }

                now.isList = isList;
                //先按照字典序排序，否则可能每次返回的child的顺序是不一定的
                for(int i = 0; i < child_Num; i++){
                    ViewNode child_node = child_list.get(i);
                    hash_string += child_node.getNodeHash();
                    if(!isList){
                        relate_hash_string += child_node.getNodeRelateHash();
                    }
                }
                now.setChildren(child_list);
                now.setNodeHash(hash_string.hashCode());
                now.setNodeRelateHash(relate_hash_string.hashCode());

            }else{
                now.setNodeHash(now.calString().hashCode());
                now.setNodeRelateHash(now.calStringWithoutPosition().hashCode());
            }
            return now;
        }
        return null;
    }


    //对于AbListView/RecyclerView/GridView等比较特殊的view，我们可能需要特殊考虑,例如计算treehash的时候可能就不需要计算到其子节点
    public static boolean isList(View root){

        boolean beFiltered = false;

        Class viewClass = root.getClass();
        for(int i = 0; i < filtsBys.length; i++) {
            beFiltered = (beFiltered || filtsBys[i].isAssignableFrom(viewClass));
            if (beFiltered) {
                return true;
            }
        }
        //RecyclerView特殊考虑，因为可能有些应用没有引入这个包，会报找不到这个类的错误
        return ViewUtil.fromRecyclerView(viewClass);
    }
}
